using System;
using System.Collections.Generic;
using System.Reflection;
using System.Xml;
using UnityEngine;

namespace EventBehaviorTree
{
    public static class NodeBuilder
    {
        public static void Gen_Nodes(XmlNode EBTNode, Container superiorNode, BindingFlags bindingFlags, object funcOwner)
        {
            NodeType nodeType = (NodeType)Enum.Parse(typeof(NodeType), EBTNode.Attributes["Type"].Value);
            EventNode node;
            XmlNode delegateNode = EBTNode.SelectSingleNode("Delegate");
            XmlNodeList delegateNodes = EBTNode.SelectNodes("Delegate");
            KeyValuePair<NodeMsg, NodeMsg>[] msgPairs = NodeMsgBuilder.GEN_MsgPairs(EBTNode.Attributes["MessagePairs"]);
            NodeMsg[] silencedMsg = NodeMsgBuilder.GEN_NodeMsgList(EBTNode.Attributes["SilencedMessage"]);
            switch (nodeType)
            {
                case NodeType.FrameCounter:
                    node = new FrameCounter(
                        (WorkMode)Enum.Parse(typeof(WorkMode), EBTNode.Attributes["WorkMode"].Value),
                        int.Parse(EBTNode.Attributes["Duration"].Value), msgPairs, silencedMsg);
                    break;
                case NodeType.InstantCondition:
                    node = new InstantCondition(DelegateBuilder.GetCondition(delegateNode, bindingFlags, funcOwner));
                    break;
                case NodeType.Sentinel:
                    node = new Sentinel(DelegateBuilder.GetCondition(delegateNode, bindingFlags, funcOwner));
                    break;
                case NodeType.Repeater:
                    node = new Repeater(EBTNode.Attributes["repeatLimit"] == null ? 0 :
                        int.Parse(EBTNode.Attributes["repeatLimit"].Value), msgPairs, silencedMsg);
                    break;
                case NodeType.Selector:
                    node = new Selector(msgPairs, silencedMsg);
                    break;
                case NodeType.Sequencer:
                    node = new Sequencer(msgPairs, silencedMsg);
                    break;
                case NodeType.StateSwitcher:
                    node = new StateSwitcher(msgPairs, silencedMsg);
                    break;
                case NodeType.Asynchronous:
                    node = new Asynchronous(DelegateBuilder.GetAction(delegateNodes, bindingFlags, funcOwner));
                    break;
                case NodeType.InstantTask:
                    node = new InstantTask(DelegateBuilder.GetAction(delegateNodes, bindingFlags, funcOwner));
                    break;
                default:
                    return;
            }
            superiorNode.AddSubNode(node);
            XmlNodeList subNodes = EBTNode.SelectNodes("Node");
            if (subNodes.Count > 0)
            {
                foreach (XmlNode subNode in subNodes) Gen_Nodes(subNode, (Container)node, bindingFlags, funcOwner);
            }
        }
    }
}